#include <iostream>
#include <queue>
#include <vector>
#include <memory>
#include "Cond.hpp"
#include "Mutex.hpp"
#include "Thread.hpp"
#include "Logger.hpp"
#include "Task.hpp"

const static int defaultthreadnum = 3;

template<class T>
class ThreadPool
{
private:
    bool QueueIsEmpty()
    {
        return _q.empty();
    }
    void Routine(const std::string &name)
    {
        while(1)
        {
            T t;
            {
                LockGuard lockguard(&_lock);
                while(QueueIsEmpty() && _is_running)
                {
                    _wait_thread_num++;
                    _cond.Wait(_lock);
                    _wait_thread_num--;
                }
                if(!_is_running && QueueIsEmpty())
                {
                    LOG(LogLevel::DEBUG) << "pthreadpool exit " << name << " exit";
                    break;
                }
                //到这里说明任务队列中一定有任务，但是
                //1、线程退出，消耗历史任务
                //2、线程没退出，正常执行任务
                t = _q.front();
                _q.pop();
            }
            t();
            LOG(LogLevel::DEBUG) << name << " handler task: " << t.Result2String();
        }
    }
public:
    //构造函数
    ThreadPool(int threadnum = defaultthreadnum)
        :_is_running(false),
         _threadnum(threadnum),
         _wait_thread_num(0)
    {
        //创建线程
        for(int i = 0 ; i < _threadnum ; i++)
        {
            std::string name = "thread-" + std::to_string(i + 1);
            //需要跟Thread类构建链接，加强耦合性
            _thread.emplace_back([this](const std::string &name){this->Routine(name);}, name);
        }
        LOG(LogLevel::INFO) << "threadpoll obj create success!";
    }
    //启动线程池
    void Start()
    {
        if(_is_running)
            return ;
        _is_running = true;
        for(auto &t : _thread)
        {
            t.Start();
        }
        LOG(LogLevel::INFO) << "thread create success!";
    }
    //关闭线程池
    //线程退出
    //1.线程被唤醒 && 任务队列没有任务 -> 线程退出
    //2.线程被唤醒 && 任务队列还有任务 -> 完成剩下的任务再退出
    //3.线程没有被休眠 && 任务队列还有任务 -> 唤醒线程，完成能完成的任务，再退出
    void Stop()
    {
        if(!_is_running)
            return ;
        _is_running = false;
        if(_wait_thread_num)
            _cond.NotifyAll();
        LOG(LogLevel::INFO) << "thread stop success!";
    } 
    //线程等待
    void Wait()
    {
        for(auto &t : _thread)
        {
            t.Join();
        }
        LOG(LogLevel::INFO) << "thread wait success!";
    }
    //插入数据
    void Enqueue(const T& t)
    {
        if(!_is_running)
            return ;
        {
            LockGuard lockguard(&_lock);
            _q.push(t);
            if (_wait_thread_num > 0)
                _cond.NotifyOne();
        }
    }
    //析构函数
    ~ThreadPool()
    {

    }
private:
    std::queue<T> _q; //任务队列（临界资源）
    std::vector<Thread> _thread; //创建线程
    int _threadnum;
    int _wait_thread_num;

    Mutex _lock; //保护机制
    Cond _cond;

    bool _is_running; //线程池启动判断
};